/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2022-2023. All rights reserved.
 */

package toolcbc

import (
	"prim-server/config"
	"strings"

	"github.com/google/uuid"
	"github.com/huaweicloud/huaweicloud-sdk-go-v3/core/auth/global"
	bss "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/bss/v2"
	bssModel "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/bss/v2/model"
	bssRegion "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/bss/v2/region"
	"github.com/spf13/cast"
)

const (
	nameSearch    = "name"
	emailSearch   = "email"
	mobileSearch  = "mobile"
	closeMarketMs = "true"
	openMarketMs  = "false"

	useCoupon      = "YES"
	useDiscount    = "YES"
	notUseCoupon   = "NO"
	notUseDiscount = "NO"
)

const (
	//个人认证认证结果
	AuthenticationUnderReview = 0
	AuthenticationReject      = 1
	AuthenticationPassed      = 2

	//个人实名认证方案
	IdentifyTypeOfIDCard   = 0
	IdentifyTypeOfBankCard = 4

	//证件类型
	VerifiedTypeOfIDCard                 = 0
	VerifiedTypeOfPassport               = 3
	VerifiedTypeOfHKMacaoPass            = 5
	VerifiedTypeOfTaiWanPass             = 6
	VerifiedTypeOfHKMacaoResidencePermit = 9
	VerifiedTypeOfTaiwanResidencePermit  = 10

	//变更类型
	FirstChangeType = -1
)

var (
	bbsAK           = config.GetConfig().BSSConfig.AK
	bbsSK           = config.GetConfig().BSSConfig.SK
	bbsEndpoint     = config.GetConfig().BSSConfig.Endpoint
	bbsXAccountType = config.GetConfig().BSSConfig.XAccountType
)

var bssClient *bss.BssClient
var myBssClient *MyBssClient

func GetMyBssClient() *MyBssClient {
	if myBssClient == nil {
		myBssClient = &MyBssClient{}
		myBssClient.BssClient = getBssClient()
	}
	return myBssClient
}

// 查询客户云上账户信用额度
func QueryCloudCreditCoupons(cloudUserIds []string) (*QueryCloudCreditCouponsResponse, error) {
	client := GetMyBssClient()
	request := &QueryCloudCreditCouponsRequest{}
	request.Body = &QueryCreditCouponsBody{
		CustomerIds: cloudUserIds,
	}
	response, err := client.queryCloudCreditCoupons(request)
	if err != nil {
		return nil, err
	}
	return response, nil
}

// 调整客户云上账户信用额度
func AdjustCloudCreditCoupons(cloudUserId string, adjustType int32, amount float64) (*AdjustCloudCreditCouponReponse, error) {
	client := GetMyBssClient()
	request := &AdjustCloudCreditCouponRequest{}
	request.Body = &AdjustCloudCreditCouponBody{
		CustomerId: cloudUserId,
		AdjustType: adjustType,
		Amount:     amount,
	}
	response, err := client.adjustCloudCreditCoupon(request)
	if err != nil {
		return nil, err
	}
	return response, nil
}

// 查询客户云上账户信用额度调整记录
func QueryCloudCreditRecord(cloudUserId string, offset, limit *int32) (*QueryCloudCreditRecordResponse, error) {
	client := GetMyBssClient()
	request := &QueryCloudCreditRecordRequest{
		CustomerId: cloudUserId,
		Offset:     offset,
		Limit:      limit,
	}
	response, err := client.queryCloudCreditRecord(request)
	if err != nil {
		return nil, err
	}
	return response, nil
}

// 使用临时AKSK创建鉴权
func getTempBssClient(tempAK, tempSK, tempSecurityToken string) *bss.BssClient {
	auth := global.NewCredentialsBuilder().
		WithAk(tempAK).
		WithSk(tempSK).
		WithSecurityToken(tempSecurityToken).
		Build()
	tempBssClient := bss.NewBssClient(
		bss.BssClientBuilder().
			WithRegion(bssRegion.ValueOf("cn-north-1")).
			WithCredential(auth).
			Build())
	return tempBssClient
}

func getBssClient() *bss.BssClient {
	if bssClient == nil {
		auth := global.NewCredentialsBuilder().
			WithAk(bbsAK).
			WithSk(bbsSK).
			Build()
		bssClient = bss.NewBssClient(
			bss.BssClientBuilder().
				WithRegion(bssRegion.ValueOf("cn-north-1")).
				WithCredential(auth).
				Build())
	}
	return bssClient
}

// 校验客户注册信息
func checkIdentity(searchType, searchValue string) error {
	request := &bssModel.CheckUserIdentityRequest{}
	request.Body = &bssModel.CheckSubcustomerUserReq{
		SearchType:  searchType,
		SearchValue: searchValue,
	}
	_, err := getBssClient().CheckUserIdentity(request)
	if err != nil {
		return err
	}
	return nil
}

// CreatCloudUser创建云上用户,默认以账号形式进行创建
func CreatCloudUser(userId, userName string) (cloudId, cloudName, cloudPassword string, err error) {
	var marketMs string = closeMarketMs
	cloudPassword = GetRandanPassword()
	//默认关闭营销信息的发送
	request := &bssModel.CreateSubCustomerRequest{}
	request.Body = &bssModel.CreateCustomerV2Req{
		XaccountId:      userId,
		XaccountType:    bbsXAccountType,
		IsCloseMarketMs: &marketMs,
		Password:        &cloudPassword,
	}
	response, err := getBssClient().CreateSubCustomer(request)
	if err != nil {
		return "", "", "", err
	}
	if response.DomainId == nil {
		return "", "", "", nil
	}
	return *response.DomainId, *response.DomainName, cloudPassword, nil
}

// 生成随机密码uuid
func GetRandanPassword() string {
	rawStr := uuid.New()
	key := rawStr.String()
	uid := strings.Replace(key, "-", "", -1)
	return uid
}

// 构造个人提起实名认证的请求体
func BuildApplyIndividualRealnameAuthsReq(cloudUserId, xAccountType, realName, verifiedNumber string,
	identifyType int32, verifiedType *int32, verifiedFileUrl []string) *bssModel.ApplyIndividualRealnameAuthsReq {
	changeType := int32(-1)
	switch identifyType {
	case IdentifyTypeOfIDCard:
		request := &bssModel.ApplyIndividualRealnameAuthsReq{
			CustomerId:      cloudUserId,
			IdentifyType:    identifyType,
			VerifiedFileUrl: verifiedFileUrl,
			Name:            realName,
			VerifiedNumber:  verifiedNumber,
			XaccountType:    xAccountType,
			VerifiedType:    verifiedType,
			BankCardInfo:    nil,
			ChangeType:      &changeType,
		}
		return request
	default:
		return nil
	}

}

// 个人提起实名认证
func RealNameAuthenticationPerson(requestBody bssModel.ApplyIndividualRealnameAuthsReq) (*bssModel.CreatePersonalRealnameAuthResponse, error) {
	client := getBssClient()
	request := &bssModel.CreatePersonalRealnameAuthRequest{}
	request.Body = &requestBody
	response, err := client.CreatePersonalRealnameAuth(request)
	if err != nil {
		return nil, err
	}
	return response, nil
}

// 查询实名认证审核结果
func GetRealNameAuthentication(cloudUserId string) (*bssModel.ShowRealnameAuthenticationReviewResultResponse, error) {
	client := getBssClient()
	request := &bssModel.ShowRealnameAuthenticationReviewResultRequest{
		CustomerId: cloudUserId,
	}
	response, err := client.ShowRealnameAuthenticationReviewResult(request)
	if err != nil {
		return nil, err
	}
	return response, nil
}

// 查询客户账户余额--代售客户使用
func GetBalanceDetail(cloudUserId string) (*bssModel.ListCustomersBalancesDetailResponse, error) {
	client := getBssClient()
	request := &bssModel.ListCustomersBalancesDetailRequest{}
	body := []bssModel.CustomerInfoV2{
		{
			CustomerId: cloudUserId,
		},
	}
	request.Body = &bssModel.QueryCustomersBalancesReq{
		CustomerInfos: body,
	}
	response, err := client.ListCustomersBalancesDetail(request)
	if err != nil {
		return nil, err
	}
	return response, nil
}

// 构建订单查询条件,为空时不作为筛选条件
func buildRequestForGetCloudOrders(cloudOrderId, cloudUserId, createTimeBegin, createTimeEnd,
	serviceTypeCode, orderType, orderBy, paymentTimeBegin, paymentTimeEnd, indirectPartnerId *string,
	orderStatus, limit, offset *int32) *bssModel.ListCustomerOrdersRequest {
	requestBody := &bssModel.ListCustomerOrdersRequest{
		OrderId:           cloudOrderId,
		CustomerId:        cloudUserId,
		CreateTimeBegin:   createTimeBegin,
		CreateTimeEnd:     createTimeEnd,
		ServiceTypeCode:   serviceTypeCode,
		Status:            orderStatus,
		OrderType:         orderType,
		Limit:             limit,
		Offset:            offset,
		OrderBy:           orderBy,
		PaymentTimeBegin:  paymentTimeBegin,
		PaymentTimeEnd:    paymentTimeEnd,
		IndirectPartnerId: indirectPartnerId,
	}
	return requestBody
}

// 查询客户云上包周期订单
func GetCloudOrders(cloudOrderId, cloudUserId, createTimeBegin, createTimeEnd,
	serviceTypeCode, orderType, orderBy, paymentTimeBegin, paymentTimeEnd, indirectPartnerId *string,
	orderStatus, limit, offset *int32) (*bssModel.ListCustomerOrdersResponse, error) {
	return GetCloudOrdersWithRequest(buildRequestForGetCloudOrders(cloudOrderId, cloudUserId, createTimeBegin, createTimeEnd,
		serviceTypeCode, orderType, orderBy, paymentTimeBegin, paymentTimeEnd, indirectPartnerId,
		orderStatus, limit, offset))
}
func GetCloudOrdersWithRequest(requestBody *bssModel.ListCustomerOrdersRequest) (*bssModel.ListCustomerOrdersResponse, error) {
	client := getBssClient()
	response, err := client.ListCustomerOrders(requestBody)
	if err != nil {
		return nil, err
	}
	return response, nil
}

// 构建查询包周期订单详情请求体
func buildRequestForGetCloudOnePayOrderDetail(cloudOrderId string, limit, offset *int32, indirectPartnerId *string) *bssModel.ShowCustomerOrderDetailsRequest {
	request := &bssModel.ShowCustomerOrderDetailsRequest{
		OrderId:           cloudOrderId,
		Limit:             limit,
		Offset:            offset,
		IndirectPartnerId: indirectPartnerId,
	}
	return request
}

// 查询包周期订单详情
func GetCloudOnePayOrderDetailWithRequest(requestbody *bssModel.ShowCustomerOrderDetailsRequest) (*bssModel.ShowCustomerOrderDetailsResponse, error) {
	client := getBssClient()
	response, err := client.ShowCustomerOrderDetails(requestbody)
	if err != nil {
		return nil, err
	}
	return response, nil
}
func GetCloudOnePayOrderDetail(cloudOrderId string, limit, offset *int32, indirectPartnerId *string) (*bssModel.ShowCustomerOrderDetailsResponse, error) {
	return GetCloudOnePayOrderDetailWithRequest(buildRequestForGetCloudOnePayOrderDetail(cloudOrderId, limit, offset, indirectPartnerId))
}

// 构建查询客户云上按需资源条件,为空时不作为筛选条件
func buildResquestForGetCloudOnDemandResources(cloudUserId string,
	regionCode, serviceTypeCode, effectiveTimeBegin, effectiveTimeEnd, indirectPartnerId *string,
	resourceIds *[]string, offset, limit, resourceStatus *int32) *bssModel.ListCustomerOnDemandResourcesRequest {
	request := &bssModel.ListCustomerOnDemandResourcesRequest{}
	request.Body = &bssModel.QueryCustomerOnDemandResourcesReq{
		CustomerId:         cloudUserId,
		RegionCode:         regionCode,
		ServiceTypeCode:    serviceTypeCode,
		ResourceIds:        resourceIds,
		EffectiveTimeBegin: effectiveTimeBegin,
		EffectiveTimeEnd:   effectiveTimeEnd,
		Offset:             offset,
		Limit:              limit,
		Status:             resourceStatus,
		IndirectPartnerId:  indirectPartnerId,
	}
	return request
}

// 查询客户云上按需资源
func GetCloudOnDemandResources(cloudUserId string,
	regionCode, serviceTypeCode, effectiveTimeBegin,
	effectiveTimeEnd, indirectPartnerId *string,
	resourceIds *[]string, offset, limit, resourceStatus *int32) (*bssModel.ListCustomerOnDemandResourcesResponse, error) {
	return GetCloudOnDemandResourcesWithRequest(buildResquestForGetCloudOnDemandResources(
		cloudUserId, regionCode, serviceTypeCode, effectiveTimeBegin,
		effectiveTimeEnd, indirectPartnerId, resourceIds, offset, limit, resourceStatus))
}
func GetCloudOnDemandResourcesWithRequest(requestBody *bssModel.ListCustomerOnDemandResourcesRequest) (*bssModel.ListCustomerOnDemandResourcesResponse, error) {
	client := getBssClient()
	response, err := client.ListCustomerOnDemandResources(requestBody)
	if err != nil {
		return nil, err
	}
	return response, nil
}

// 构建支付订单请求体--默认不使用优惠券和折扣
func buildRequestForPayCustomerOrder(orderId string, couponInfos []bssModel.CouponSimpleInfoOrderPayV3, discountInfos []bssModel.DiscountSimpleInfoV3) *bssModel.PayOrdersRequest {
	request := &bssModel.PayOrdersRequest{}
	request.Body = &bssModel.PayCustomerOrderV3Req{
		OrderId:     orderId,
		UseCoupon:   notUseCoupon,
		UseDiscount: notUseDiscount,
	}
	if len(couponInfos) > 0 {
		request.Body.UseCoupon = useCoupon
		request.Body.CouponInfos = &couponInfos
	}
	if len(discountInfos) > 0 {
		request.Body.UseDiscount = useDiscount
		request.Body.DiscountInfos = &discountInfos
	}
	return request
}

// 支付订单--使用客户的临时AKSK支付订单
func PayCloudOnePayOrder(cloudUserId, cloudOrderId string, cloudCoupon []bssModel.CouponSimpleInfoOrderPayV3, cloudDiscount []bssModel.DiscountSimpleInfoV3) (*bssModel.PayOrdersResponse, error) {
	tempAK, tempSK, tempSecurityToken, err := getTempSubClientAKSK(cloudUserId)
	if err != nil {
		return nil, err
	}
	client := getTempBssClient(tempAK, tempSK, tempSecurityToken)
	request := buildRequestForPayCustomerOrder(cloudOrderId, cloudCoupon, cloudDiscount)
	response, err := client.PayOrders(request)
	if err != nil {
		return nil, err
	}
	return response, nil
}

// 取消待支付订单--使用客户的临时AKSK取消订单
func CancelCloudOnePayOrder(cloudUserId, cloudOrderId string) (*bssModel.CancelCustomerOrderResponse, error) {
	tempAK, tempSK, tempSecurityToken, err := getTempSubClientAKSK(cloudUserId)
	if err != nil {
		return nil, err
	}
	client := getTempBssClient(tempAK, tempSK, tempSecurityToken)
	request := &bssModel.CancelCustomerOrderRequest{}
	request.Body = &bssModel.CancelCustomerOrderReq{
		OrderId: cloudOrderId,
	}
	response, err := client.CancelCustomerOrder(request)
	if err != nil {
		return nil, err
	}
	return response, nil
}

// 查询包年包月资源列表 -- 使用客户的临时AKSK
func GetListPayUseResources(cloudUserId string) (*bssModel.ListPayPerUseCustomerResourcesResponse, error) {
	tempAK, tempSK, tempSecurityToken, err := getTempSubClientAKSK(cloudUserId)
	if err != nil {
		return nil, err
	}
	client := getTempBssClient(tempAK, tempSK, tempSecurityToken)
	request := &bssModel.ListPayPerUseCustomerResourcesRequest{}
	request.Body = &bssModel.QueryResourcesReq{}
	response, err := client.ListPayPerUseCustomerResources(request)
	if err != nil {
		return nil, err
	}
	return response, nil
}

// 退订包年包月资源--使用客户的临时AKSK退订包年包月资源
func CancelResourcesSubscription(cloudUserId string, cloudResourceIds []string, unsubscribeType int32) (*bssModel.CancelResourcesSubscriptionResponse, error) {
	tempAK, tempSK, tempSecurityToken, err := getTempSubClientAKSK(cloudUserId)
	if err != nil {
		return nil, err
	}
	client := getTempBssClient(tempAK, tempSK, tempSecurityToken)
	request := &bssModel.CancelResourcesSubscriptionRequest{}
	request.Body = &bssModel.UnsubscribeResourcesReq{
		UnsubscribeType: unsubscribeType,
		ResourceIds:     cloudResourceIds,
	}
	response, err := client.CancelResourcesSubscription(request)
	if err != nil {
		return response, err
	}
	return response, nil
}
func buildParameterForGetCustomerBillRecord(billCycle string,
	serviceTypeCode, resourceTypeCode, regionCode, tradeId, billDateBegin, billDateEnd, chargeMode *string,
	billType, billStatus, offset, limit *int32, includeZeroRecord *bool) *bssModel.ListCustomerBillsFeeRecordsRequest {
	request := &bssModel.ListCustomerBillsFeeRecordsRequest{
		BillCycle:         billCycle,
		ServiceTypeCode:   serviceTypeCode,
		ResourceTypeCode:  resourceTypeCode,
		RegionCode:        regionCode,
		TradeId:           tradeId,
		BillDateBegin:     billDateBegin,
		BillDateEnd:       billDateEnd,
		BillType:          billType,
		Status:            billStatus,
		Offset:            offset,
		Limit:             limit,
		IncludeZeroRecord: includeZeroRecord,
	}
	if chargeMode != nil {
		tempChargeMode := cast.ToInt32(*chargeMode)
		request.ChargingMode = &tempChargeMode
	}
	return request
}

// 查询流水账单--使用客户临时AKSK
func GetBiilRecord(cloudUserId, billCycle string,
	serviceTypeCode, resourceTypeCode, regionCode, tradeId, billDateBegin, billDateEnd, chargeMode *string,
	billType, billStatus, offset, limit *int32, includeZeroRecord *bool) (*bssModel.ListCustomerBillsFeeRecordsResponse, error) {
	tempAK, tempSK, tempSecurityToken, err := getTempSubClientAKSK(cloudUserId)
	if err != nil {
		return nil, err
	}
	client := getTempBssClient(tempAK, tempSK, tempSecurityToken)
	request := buildParameterForGetCustomerBillRecord(billCycle, serviceTypeCode,
		resourceTypeCode, regionCode, tradeId, billDateBegin, billDateEnd,
		chargeMode, billType, billStatus, offset, limit, includeZeroRecord)
	response, err := client.ListCustomerBillsFeeRecords(request)
	if err != nil {
		return nil, err
	}
	return response, nil
}

// 构建查询资源消费记录请求体
func buildParameterForGetResourceRecord(billCycle string,
	cloudResourceId, serviceTypeCode, regionCode, tradeId, billDateBegin, billDateEnd, chargeMode *string,
	billType, offset, limit *int32, includeZeroRecord *bool) *bssModel.ListCustomerselfResourceRecordsRequest {
	request := &bssModel.ListCustomerselfResourceRecordsRequest{
		Cycle:             billCycle,
		CloudServiceType:  serviceTypeCode,
		Region:            regionCode,
		BillType:          billType,
		Offset:            offset,
		Limit:             limit,
		ChargeMode:        chargeMode,
		ResourceId:        cloudResourceId,
		TradeId:           tradeId,
		BillDateBegin:     billDateBegin,
		BillDateEnd:       billDateEnd,
		IncludeZeroRecord: includeZeroRecord,
	}
	return request
}

// 查询资源消费记录-使用客户临时AKSK
func GetResourceRecord(cloudUserId, billCycle string,
	cloudResourceId, serviceTypeCode, regionCode, tradeId, billDateBegin, billDateEnd, chargeMode *string,
	billType, offset, limit *int32, includeZeroRecord *bool) (*bssModel.ListCustomerselfResourceRecordsResponse, error) {
	request := buildParameterForGetResourceRecord(billCycle,
		cloudResourceId, serviceTypeCode, regionCode, tradeId, billDateBegin, billDateEnd,
		chargeMode, billType, offset, limit, includeZeroRecord)
	return GetResourceRecordWithParameter(cloudUserId, request)
}

func GetResourceRecordWithParameter(cloudUserId string, request *bssModel.ListCustomerselfResourceRecordsRequest) (*bssModel.ListCustomerselfResourceRecordsResponse, error) {
	tempAK, tempSK, tempSecurityToken, err := getTempSubClientAKSK(cloudUserId)
	if err != nil {
		return nil, err
	}
	client := getTempBssClient(tempAK, tempSK, tempSecurityToken)
	response, err := client.ListCustomerselfResourceRecords(request)
	if err != nil {
		return nil, err
	}
	return response, nil
}
